/*
 * Copyright 2013 Pavel Stastny <pavel.stastny at gmail.com>.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.aplikator.server.processes.impl.processes.ipc.sharedfolder;

import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.Comparator;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.aplikator.server.processes.impl.processes.ipc.IPCChannel;
import org.aplikator.server.processes.impl.processes.ipc.IPCMessage;
import org.aplikator.server.processes.impl.processes.ipc.impl.IPCMessageImpl;
import org.aplikator.server.util.IOUtils;
import org.json.JSONException;

/**
 *
 * @author Pavel Stastny <pavel.stastny at gmail.com>
 */
public class SharedFolderChannel implements IPCChannel {
    
    
    public static final Logger LOGGER = Logger.getLogger(SharedFolderChannel.class.getName());
    
    private String appname;

    public SharedFolderChannel(String appname) {
        this.appname = appname;
    }
    
    
    @Override
    public void sendMessage(IPCMessage message) throws IOException {
        File f = SharedFolderSingleton.getSharedFolder(this.appname).allocFileName(createFileName(message));
        IOUtils.saveToFile(message.storeToBytes(Charset.forName("UTF-8")), f);
    }

    @Override
    public IPCMessage receiveMessage() throws IOException {
        try {
            File f = popFile(files(null));
            if (f != null) {
                byte[] bytes = IOUtils.readBytes(new FileInputStream(f), true);
                IPCMessage message = IPCMessageImpl.readMessageFromBytes(bytes, Charset.forName("UTF-8"));
                f.delete();
                return message;
            } else return null;
        } catch(JSONException ex) {
            LOGGER.log(Level.SEVERE, ex.getMessage(),ex);
            return null;
        }
    }

    
    
    @Override
    public IPCMessage receiveMessage(final String address) throws IOException {
        try {
            File f = popFile(files(new FileFilter() {

                @Override
                public boolean accept(File pathname) {
                    String name = pathname.getName();
                    String[] n = name.split("::");
                    String pattern = address+"\\.\\d*";
                    return (n.length == 2 && n[1].matches(pattern));
                }
            }));
            if (f != null) {
                byte[] bytes = IOUtils.readBytes(new FileInputStream(f), true);
                IPCMessage message = IPCMessageImpl.readMessageFromBytes(bytes, Charset.forName("UTF-8"));
                f.delete();
                return message;
            } else return null;
        } catch(JSONException ex) {
            LOGGER.log(Level.SEVERE, ex.getMessage(),ex);
            return null;
        }
    }

    private File[] files(FileFilter filter) {
        File f = SharedFolderSingleton.getSharedFolder(this.appname).getFolder();
        File[] listFiles = filter == null ? f.listFiles() : f.listFiles(filter);
        return listFiles;
    }

    
    private File popFile(File[] listFiles) {
        if (listFiles != null) {
            Arrays.sort(listFiles, new Comparator<File>() {
                @Override
                public int compare(File o1, File o2) {
                    String name1 = o1.getName();
                    String name2 = o2.getName();
                    Integer val1 = Integer.valueOf(name1.split("_")[0]);
                    Integer val2 = Integer.valueOf(name2.split("_")[0]);
                    return val1.compareTo(val2);
                }
            });
            return (listFiles.length > 0) ? listFiles[0] : null;
        } else return null;
    }

    private String createFileName(IPCMessage message) {
        return message.getSourceAddress()+"::"+message.getDestAddress();
    }
    
}
